// Copyright 2013 Google Inc. All Rights Reserved.

#include <unistd.h>

#include <bionic/pthread_internal.h>
#include <irt_syscalls.h>

void _exit_thread() {
  pthread_internal_t* thread = __get_thread();
  // Let NaCl service runtime fill zero to the thread ID after
  // untrusted code finshes completely. pthread_join will wait for
  // this to check if it is safe to unmap the stack of this thread.
  //
  // nacl-glibc/nptl/pthread_create.c also lets service runtime update
  // the thread ID.
  __nacl_irt_thread_exit(&thread->kernel_id);

  // This should not happen.
  static const int kStderrFd = 2;
  static const char kMsg[] = "__nacl_irt_thread_exit failed\n";
  write(kStderrFd, kMsg, sizeof(kMsg) - 1);

#if defined(__x86_64__) || defined(__i386__)
  while (1)
    __asm__("hlt");
#else
  // For nacl_arm. sfi_constant_barrier is expanded to a bkpt instruction
  // which passes the validation.
  __asm__(".balign 16\n"
          "bkpt 0x5be0\n"
          ".balign 16");
#endif
}
